package pers.qianyu.diytomcat.catalina;

import cn.hutool.core.io.*;
import cn.hutool.core.util.*;
import cn.hutool.log.*;
import pers.qianyu.diytomcat.constants.*;
import pers.qianyu.diytomcat.util.*;
import pers.qianyu.diytomcat.watcher.*;

import java.io.*;
import java.util.*;

/**
 * 虚拟主机
 *
 * @author mizzle rain
 * @date 2021-01-07 15:56
 */
public class Host {
    private String name;
    private Engine engine;
    private Map<String, Context> path2Context;

    public Host(String name, Engine engine) {
        this.name = name;
        this.engine = engine;
        path2Context = new HashMap<>();
        scanContextsInWebappsFolder();
        scanContextsInServerXml();
        scanWarInWebappFolder();
        new WarFileWatcher(this).start();
    }

    public Context getContext(String path) {
        return path2Context.get(path);
    }

    private void scanContextsInWebappsFolder() {
        File[] files = Locations.WEBAPPS_FOLDER.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                loadContext(file);
            }
        }
    }

    private void scanContextsInServerXml() {
        List<Context> contexts = ServerXmlUtil.getContexts(this);
        contexts.forEach(c -> path2Context.put(c.getPath(), c));
    }

    private void scanWarInWebappFolder() {
        File[] files = FileUtil.file(Locations.WEBAPPS_FOLDER).listFiles();
        if (null != files) {
            for (File file : files) {
                if (file.getName().toLowerCase().endsWith(".war")) {
                    loadWarFile(file);
                }
            }
        }
    }

    private void loadContext(File folder) {
        String path;
        if (Objects.equals("ROOT", folder.getName())) {
            path = "/";
        } else {
            path = "/" + folder.getName();
        }
        String docBase = folder.getAbsolutePath();
        Context context = new Context(path, docBase, this, true);
        path2Context.put(path, context);
    }

    public void reload(Context context) {
        LogFactory.get().info("Reloading Context with name [{}] has started", context.getPath());
        String docBase = context.getDocBase();
        String path = context.getPath();
        boolean reloadable = context.isReloadable();
        context.stop();
        Context newContext = new Context(path, docBase, this, reloadable);
        path2Context.put(path, newContext);
        LogFactory.get().info("Reloading Context with name [{}] has completed", context.getPath());
    }

    public void loadWarFile(File warFile) {
        String warFileName = warFile.getName();
        String folderName = StrUtil.subBefore(warFileName, ".", false);
        if (Objects.nonNull(getContext("/" + folderName))) {
            return;
        }
        File unzipFolder = FileUtil.file(Locations.WEBAPPS_FOLDER, folderName);
        if (unzipFolder.exists()) {
            return;
        }
        unzipFolder.mkdirs();
        File tempWarFile = FileUtil.file(unzipFolder, warFileName);
        FileUtil.copy(warFile, tempWarFile, true);
        Process p = RuntimeUtil.exec(null, unzipFolder, "jar xvf " + warFileName);
        try {
            p.waitFor();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        tempWarFile.delete();
        loadContext(unzipFolder);
    }

    /************** automatic generated *****************/
    public Engine getEngine() {
        return engine;
    }

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Map<String, Context> getPath2Context() {
        return path2Context;
    }

    public void setPath2Context(Map<String, Context> path2Context) {
        this.path2Context = path2Context;
    }
}
